﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using NLog;
using System.Text;

using @LOGGER = Microsoft.Extensions.Logging.ILogger;
namespace Kz.Telegram.Bot.Infrastructure.Middlewares
{
    /// <summary>
    /// 全局日志记录中间件
    /// </summary>
    public class GlobalLogMiddleware
    {
        private readonly RequestDelegate next;
        private readonly @LOGGER _logger;

        public GlobalLogMiddleware(RequestDelegate next, ILogger<GlobalLogMiddleware> logger)
        {
            this.next = next;
            this._logger = logger;
        }

        /// <summary>
        /// 实现Invoke方法
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task Invoke(HttpContext context)
        {
            try
            {
                #region 设置跟踪的RequestID

                var requestKey = "RequestId";
                if (!context.Request.Headers.TryGetValue(requestKey, out var requestID))
                {
                    requestID = $"{Guid.NewGuid().ToString().Replace("-", "")}";
                    context.Request.Headers.Add("RequestId", $"{requestID}");
                }
                MappedDiagnosticsContext.Set("RequestId", requestID.First());

                #endregion

                #region  入参
                var url = context.Request.Path + context.Request.QueryString.Value ?? "";
                var paramters = new StringBuilder();

                //form中的参数,但是忽略File文件
                if (context.Request.HasFormContentType)
                {
                    int i = 0;
                    foreach (var item in context.Request.Form.Keys)
                    {
                        paramters.Append(string.Format("{2}{0}={1}", item, context.Request.Form[item], (i == 0) ? "" : "&"));
                        i++;
                    }
                }
                else
                {
                    context.Request.EnableBuffering();
                    var requestReader = new StreamReader(context.Request.Body);
                    var requestContent = await requestReader.ReadToEndAsync();
                    paramters.Append(requestContent);
                    context.Request.Body.Position = 0;
                }

                _logger.LogInformation($"Request URL：{url}  Params：{paramters}");
                #endregion

                #region 响应
                var originalResponseStream = context.Response.Body;
                using (var ms = new MemoryStream())
                {
                    context.Response.Body = ms;
                    await next.Invoke(context);

                    ms.Position = 0;
                    var responseReader = new StreamReader(ms);
                    var responseContent = await responseReader.ReadToEndAsync();

                    _logger.LogInformation($"Response Url:{context.Request.Path}  Body:{responseContent}");

                    ms.Position = 0;
                    await ms.CopyToAsync(originalResponseStream);
                    context.Response.Body = originalResponseStream;
                }
                #endregion
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}
